;*******************************************************************************
; Director - Edit
;
; Copyright (C) 2003, Nick Craig-Wood and Philip Ludlam
;
;This program is free software; you can redistribute it and/or modify it under
;the terms of the GNU General Public License as published by the Free Software
;Foundation; either version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful, but WITHOUT ANY
;WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
;PARTICULAR PURPOSE. See the GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License along with
;this program; if not, write to the Free Software Foundation, Inc., 59 Temple
;Place - Suite 330, Boston, MA 02111-1307, USA
;
;*******************************************************************************
;----h- Director.s.Edit
; Name
;   Edit
;
; Purpose
;   Provide the DirectorEdit call.
;------
;*******************************************************************************


		TTL	> Edit

		GET	OSLib:oslib.hdr.Wimp
		GET	AsmLib2:hdr.RegsBoth
		GET	AsmLib2:hdr.MacrosBoth
		GET	h.WorkSpace
		GET	h.ListMacros
		GET	h.Constants
		GET	h.Memory
		GET	h.Task
		GET	h.Menus
		GET	h.Messages
		GET	h.BMG
		GET	h.ModuleHead

		AREA	|Edit|, CODE, READONLY


;*******************************************************************************
;----s- Director.s.Edit.EditBlockStructure
; Name
;   EditBlock structure
;
; Source

			^	0
EditBlock_link		#	4	;  next EditBlock (or NULL if none)
EditBlock_file		#	4	;  filename
EditBlock_handle	#	4	; handle of wimp message (used to find
					;   a text editor)
EditBlock_quiet		#	4	; Report error if problem
EditBlock		EQU	:INDEX: @

;------
;*******************************************************************************


;*******************************************************************************
;----f- Director.s.Edit.EditBlockFind
; Name
;   EditBlockFind
;
; Function
;   This finds the given edit (file) block in the edit (file) list
;   or returns a pointer to the previous item
;
; Entry
;   r0  name of file
;
; Exit
;   r0  EditBlock
;   r1  previous edit (file) block (if found)
;   Flags:
;     EQ means found
;     NE means not found
;------
;*******************************************************************************


EditBlockFind	ROUTINE	"r2-r4"

		ADR	r4, EditAnchor			; r4  list anchor

loop$l		ListWalk	r4, r2			; r2  previous, r4  current
		BEQ	notfound$l

		LDR	r1, [r4, #EditBlock_file]
		BL	strcmpi				; to_find - current
		BGT	loop$l				; continue until alphabetical place found
		BNE	notfound$l

found$l		MOV	r0, r4				; point to current EditBlock
		MOV	r1, r2
		SetZ
		EXIT

notfound$l	MOV	r0, r4				; point to current EditBlock
		MOV	r1, r2
		ClearZ
		EXIT


;*******************************************************************************
;----f- Director.s.Edit.EditBlockFindHandle
; Name
;   EditBlockFindHandle
;
; Purpose
;   This finds the edit (file) block which has the wimp message handle given
;
; Entry
;   r0 = wimp message handle
;
; Exit
;   r0  EditBlock
;   r1  previous edit block (if found)
;   Flags:
;     EQ means found
;     NE means not found
;------
;*******************************************************************************


EditBlockFindHandle	ROUTINE	"r2-r4"

		MOV	r2, r0				; r2 = handle to find
		ADR	r0, EditAnchor			; r0  EditBlock

find$l		ListWalk	r0, r1			; r0  EditBlock, r1  previous
		BEQ	notfound$l
		LDR	lr, [r0, #EditBlock_handle]
		CMP	lr, r2
		BNE	find$l

found$l		SetZ
		EXIT

notfound$l	ClearZ
		EXIT


;*******************************************************************************
;----f- Director.s.Edit.EditBlockDestroy
; Name
;   EditBlockDestroy
;
; Purpose
; This destroys a edit (file) block and unlinks it from the list.
; It releases any memory attached also.
;
; Entry
;   r0  EditBlock
;   r1  previous edit block
;------
;*******************************************************************************


EditBlockDestroy	ROUTINE	"r0-r3", EXPORT

		MOV	r3, r0				; r3  EditBlock
		UnLink	r3, r1, lr			; unlink the EditBlock

		LDR	r0, [r3, #EditBlock_file]	; free attached items
		BL	free

		MOV	r0, r3				; free block
		BL	free

		EXIT


;*******************************************************************************
;----f- Director.s.Edit.EditBlockListDestroy
; Name
;   EditBlockListDestroy
;
; Purpose
;   This destroys all the edit (file) blocks in the list.
;------
;*******************************************************************************


EditBlockListDestroy	ROUTINE	"r0-r3", EXPORT
		ADR	r0, EditAnchor

loop$l		ListWalkForDestruction	r0, r1, r2
		BEQ	exitloop$l
		BL	EditBlockDestroy
		B	loop$l

exitloop$l	EXIT


;*******************************************************************************
;----f- Director.s.Edit.DoMessage_DataOpen_Ack
; Name
;   DoMessage_DataOpen_Ack
;
; Purpose
;   Called when the WIMP sends a DataOpen message back to our task.
;   We only need to respond to it if originated from a DirectorEdit call.
;
; Entry
;   r11  message block
;
; Exit
;   none
;------
;*******************************************************************************


DoMessage_DataOpen_Ack	ROUTINE_SF "r9, r11", EXPORT
wimprun$l	#	StringSize
		END_SF

		LDR	r0, [r11, #Wimp_MessageHeader_my_ref] ; find the Edit file request which is being returned
		BL	EditBlockFindHandle		; r0  EditBlock, r1  previous
		BNE	exit$l
		MOV	r9, r1				; r9  link
		MOV	r11, r0				; r11  EditBlock

		ADR	r0, runtype$l
		ADR	r1, wimprun$l
		MOV	r2, #StringSize
		MOV	r3, #0
		MOV	r4, #0
		SWI	XOS_ReadVarVal			; r2 = the number of bytes read
		BVS	error$l

		ADR	r3, wimprun$l
		ADD	r3, r3, r2			; r3 = absolute addr in memory for end of text

		MOV	r0, #32				; = " "
loop$l
		LDRB	r1, [r3, #-1]!
		CMP	r0, r1
		BNE loop$l

		ADD	r3, r3, #1

		LDR	r0, [r11, #EditBlock_file]	; source
		MOV	r1, r3				; destination
		BL	strcpy

		ADR	r0, wimprun$l
		BL	StartWimpTask			; run the file - as if it was a text file
		BVS	cannoteditfile$l		; report error (if allowed)

exit$l
		EXIT

cannoteditfile$l
		LDR	r0, [r11, #EditBlock_quiet]	; Do we tell the user the file couldn't be loaded?
		CMP	r0, #0
		BNE	exit$l				; no, so exit

error$l		ADR	r0, errmsg$l
		BL	AlertMT
		EXIT

errmsg$l	ERROR	"$CannotEditFile", Error_CannotEditFile


runtype$l	DCB	"Alias$@RunType_FFF", 0
		ALIGN


;*******************************************************************************
;----f- Director.s.Edit.EditBlockListDirectorEdit
; Name
;   EditBlockListDirectorEdit
;
; Purpose
;   DirectorEdit has been called and set up an EditBlock.
;   First, lets send a WIMP message to see if any app can process it.
;
; Entry
;   none
;
; Exit
;   none
;------
;*******************************************************************************


EditBlockListDirectorEdit	ROUTINE_SF "r0-r3, r9, r11", EXPORT
message$l	#	256
		END_SF

		MOV	r0, #0				; find an Edit file request which hasn't been sent
		BL	EditBlockFindHandle		; r0  EditBlock, r1  previous
		BNE	nomore$l
		MOV	r9, r1				; r9  link
		MOV	r11, r0				; r0  EditBlock

		ADR	r0, message$l
		MOV	r1, #256
		BL	memclear			; set message block to 0

		LDR	r0, [r11, #EditBlock_file]
		ADR	r1, message$l + Wimp_MessageHeader_data + Wimp_MessageDataXfer_file_name
		BL	strcpy

		ADR	r0, message$l + Wimp_MessageHeader_data + Wimp_MessageDataXfer_file_name
		BL	strlen1
		ADD	r0, r0, #Wimp_MessageHeader_data + Wimp_MessageDataXfer_file_name + 3
		BIC	r0, r0, #3			; align
		STR	r0, message$l + Wimp_MessageHeader_size

		LDR	r0, =Message_DataOpen		; = 5
		STR	r0, message$l + Wimp_MessageHeader_action ; type of message

		LDR	r0, =&FFF			; text file type
		STR	r0, message$l + Wimp_MessageHeader_data + Wimp_MessageDataXfer_file_type	; set type to text

		MOV	r0, #Wimp_UserMessageRecorded	; = 18
		ADR	r1, message$l
		MOV	r2, #0				; broadcast
		SWI	XWimp_SendMessage		; send us a MouseClick event
		BVS	error$l
		LDR	r0, message$l + Wimp_MessageHeader_my_ref
		STR	r0, [r11, #EditBlock_handle]

ok$l		EXIT

nomore$l
		MOV	r0, #$Name._PollWord_DirectorEdit
		BL	BIC_PollWord
		BL	EditBlockListDestroy
		EXIT

error$l		EXIT_ERR
		LTORG


;*******************************************************************************
;----f- Director.s.Edit.DoDirectorEdit
; Name
;   DoDirector.Edit
;
; Purpose
;   This adds a DirectorEdit file to the block.
;
; Entry
;   none
;
; Exit
;   none
;------
;*******************************************************************************

Help_$Name.Edit	FOREXPORT
		[	OSVersion = 310
		DCB	"This loads the file given into an editor.", 13
		|
		DCB	"Help_DirectorEdit", 0
		]

Syntax_$Name.Edit	FOREXPORT
		[	OSVersion = 310
		DCB	"Syntax: *$Name.Edit <file> [<-q | -quiet>]", 0
		|
		DCB	"Syntax_DirectorEdit", 0
		]
		ALIGN

Args_$Name.Edit	DCB	"/g,q=quiet/s", 0
		ALIGN

Star_$Name.Edit	FOREXPORT
		LDR	wp, [r12]

Do$Name.Edit	SaveRegs
		ROUTINE_SF	NONE
scratch$l	#	0
arg_file$l	#	4
arg_quiet$l	#	4
space$l		#	scratch_size - :INDEX: @
		END_SF

		MOV	r1, r0				; translate given string
		ADR	r0, Args_$Name.Edit
		ADR	r2, scratch$l
		MOV	r3, #scratch_size
		SWI	XOS_ReadArgs
		BVS	ErrorReturn

		LDR	r0, arg_file$l
		BL	sort_out_gstrans

kill$l		BL	EditBlockFind			; r0  EditBlock, r1  previous
		BNE	exitkill$l
		BL	EditBlockDestroy
		B	kill$l

exitkill$l	MOV	r7, r1				; r7  link

		MOV	r0, #EditBlock
		BL	malloc
		BVS	ErrorReturn
		MOV	r11, r0				; r11  EditBlock
		MOV	r1, #EditBlock
		BL	memclear			; clear the edit block to 0
		LDR	r0, arg_quiet$l
		STR	r0, [r11, #EditBlock_quiet]
		LDR	r0, arg_file$l
		BL	strdup
		BVS	ErrorReturn
		STR	r0, [r11, #EditBlock_file]	; store the name of the file

		Link	r11, r7, lr			; link the block into the correct place in the list

		MOV	r0, #$Name._PollWord_DirectorEdit
		BL	ORR_PollWord			; Set the PollWord

		B	NormalReturn


;*******************************************************************************

		END
